#include "uni_iot.h"

/*
 * All header file for c language MUST be include : in extern "C" { }
 */
extern "C" {
#include "../src/uni_event_list.c"
}

static uni_sem_t sem;

H2UNIT(event_list) {
};

//---------------------------------------------------------------------------------------
static const int _event_num = 10;
static EventListHandle _handle;
static int _event_handler(Event *event) {
  static int _seq_id[_event_num] = {0}, _handled_num = 0;
  _seq_id[event->seq_id-1] = 1;
  ++_handled_num;
  if (_handled_num >= _event_num) {
    for (int i = 0; i < _event_num; ++i) {
      H2EQ_TRUE(_seq_id[i]);
    }
    uni_sem_post(sem);
  }
  return 0;
}

void _event_add(void *args) {
  EventListHandle handle = (EventListHandle)args;
  Event *event = NULL;
  int test_loop = _event_num;
  do {
    EventContent event_content = {0};
    event = EventCreate(test_loop, 0, &event_content, DefaultEventContentFreeHandler);
    if (test_loop % 3 == 0) {
      EventListAdd(handle, event, EVENT_LIST_PRIORITY_HIGHEST);
    } else if (test_loop % 3 == 1) {
      EventListAdd(handle, event, EVENT_LIST_PRIORITY_MEDIUM);
    } else {
      EventListAdd(handle, event, EVENT_LIST_PRIORITY_LOWEST);
    }
  } while(--test_loop > 0);
}

H2CASE(event_list, "EventListCreate") {
  _handle = EventListCreate(_event_handler);
  EventList *event_list = (EventList*)_handle;
  int num = event_list->highest_cnt + event_list->medium_cnt + event_list->lowest_cnt;
  H2EQ_TRUE(!num);
  EventListDestroy(_handle);
}

//---------------------------------------------------------------------------------------
H2CASE(event_list, "EventListAdd") {
  _handle = EventListCreate(_event_handler);
  _event_add(_handle);
  uni_sem_wait(sem);
  EventList *event_list = (EventList*)_handle;
  H2EQ_TRUE(!event_list->highest_cnt);
  H2EQ_TRUE(!event_list->medium_cnt);
  H2EQ_TRUE(!event_list->lowest_cnt);
  EventListDestroy(_handle);
}

//---------------------------------------------------------------------------------------
H2CASE(event_list, "EventListDestroy") {
  _handle = EventListCreate(_event_handler);
  EventList *event_list = (EventList*)_handle;
  H2EQ_TRUE(0 == EventListDestroy(_handle));
}

//---------------------------------------------------------------------------------------
static int _traverse_num = 0;
static int _traverse_handler(Event *event) {
  ++_traverse_num;
  return 0;
}
static int _event_handler2(Event *event) {//do nothing
  return 0;
}
void _consume_event_list_stub(EventList *event_list) {
}
H2CASE(event_list, "EventListTraverse") {
  H2STUB("_consume_event_list", _consume_event_list_stub);
  _handle = EventListCreate(_event_handler2);
  _event_add(_handle);
  EventListTraverse(_handle, _traverse_handler);
  H2EQ_TRUE(_traverse_num == _event_num);
  EventListDestroy(_handle);
}

//---------------------------------------------------------------------------------------
H2CASE(event_list, "EventListClear") {
  uni_sem_init(&sem, 0);
  H2STUB("_consume_event_list", _consume_event_list_stub);
  _handle = EventListCreate(_event_handler2);
  EventList *event_list = (EventList*)_handle;
  _event_add(_handle);
  int num = event_list->highest_cnt + event_list->medium_cnt + event_list->lowest_cnt;
  H2EQ_TRUE(num == _event_num);
  EventListClear(_handle);
  num = event_list->highest_cnt + event_list->medium_cnt + event_list->lowest_cnt;
  H2EQ_TRUE(!num);
  EventListDestroy(_handle);
}
